//
//  TiaoyinCanvasView.swift
//  Duyiguqin
//
//  Created by 张昭 on 2024/8/8.
//

import UIKit

class TiaoyinCanvasView: UIView {

    override init(frame: CGRect) {
        super.init(frame: frame)
        initializeSubviews()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private let startAngle: CGFloat = -150
    private let endAngle: CGFloat = -30
    private let highlightStartAngle: CGFloat = -100
    private let middleAngle: CGFloat = -90
    private let highlightEndAngle: CGFloat = -80
    private let radius: CGFloat = 150
    private var radiusCenter: CGPoint {
        return CGPoint(x: bounds.midX, y: bounds.maxY)
    }
    private var targetAngle: CGFloat = -90
    
    private lazy var topBorderLayer: CAShapeLayer = {
        let v = CAShapeLayer()
        v.fillColor = UIColor.clear.cgColor
        v.strokeColor = UIColor(0xD3C390).cgColor
        v.lineWidth = 2
        return v
    }()
    
    private lazy var leftLayer: CAShapeLayer = {
        let v = CAShapeLayer()
        v.fillColor = UIColor.clear.cgColor
        v.strokeColor = UIColor(displayP3Red: 232/255.0, green: 225/255.0, blue: 202/255.0, alpha: 1).cgColor
        v.lineWidth = 30
        return v
    }()
    
    private lazy var leftDarkLayer: CAShapeLayer = {
        let v = CAShapeLayer()
        v.fillColor = UIColor.clear.cgColor
        v.strokeColor = UIColor.white.cgColor
        v.lineWidth = 30
        return v
    }()
    
    private lazy var middleDarkLayer: CAShapeLayer = {
        let v = CAShapeLayer()
        v.fillColor = UIColor.clear.cgColor
        v.strokeColor = UIColor(0xD3C390).cgColor
        v.lineWidth = 30
        return v
    }()
    
    private lazy var rightLayer: CAShapeLayer = {
        let v = CAShapeLayer()
        v.fillColor = UIColor.clear.cgColor
        v.strokeColor = UIColor(displayP3Red: 232/255.0, green: 225/255.0, blue: 202/255.0, alpha: 1).cgColor
        v.lineWidth = 30
        return v
    }()
    
    private lazy var rightDarkLayer: CAShapeLayer = {
        let v = CAShapeLayer()
        v.fillColor = UIColor.clear.cgColor
        v.strokeColor = UIColor.white.cgColor
        v.lineWidth = 30
        return v
    }()

    private lazy var tickLayer1: CAShapeLayer = {
        let v = CAShapeLayer()
        v.strokeColor = UIColor(displayP3Red: 232/255.0, green: 225/255.0, blue: 202/255.0, alpha: 1).cgColor
        v.lineWidth = 2
        return v
    }()
    
    private lazy var tickMiddleLayer: CAShapeLayer = {
        let v = CAShapeLayer()
        v.strokeColor = UIColor(0xD3C390).cgColor
        v.lineWidth = 3
        return v
    }()
    
    private lazy var tickLayer2: CAShapeLayer = {
        let v = CAShapeLayer()
        v.strokeColor = UIColor.lightGray.cgColor
        v.lineWidth = 2
        return v
    }()
    
    private var tickLayers: [CALayer] = []
    
    private lazy var needleView: NeedleView = {
        let v = NeedleView()
        v.isHidden = true
        return v
    }()
    
    private lazy var needleBgLayer: CAShapeLayer = {
        let v = CAShapeLayer()
        v.strokeColor = UIColor.white.cgColor
        v.lineWidth = 30
        return v
    }()
    
    private lazy var leftLabel1: UILabel = {
        let v = UILabel()
        v.text = "-15"
        v.textColor = UIColor(0x808080)
        v.font = UIFont.systemFont(ofSize: 18, weight: .regular)
        return v
    }()
    
    private lazy var leftLabel2: UILabel = {
        let v = UILabel()
        v.text = "-10"
        v.textColor = UIColor(0x808080)
        v.font = UIFont.systemFont(ofSize: 18, weight: .regular)
        return v
    }()
    
    private lazy var leftLabel3: UILabel = {
        let v = UILabel()
        v.text = "-5"
        v.textColor = UIColor(0x808080)
        v.font = UIFont.systemFont(ofSize: 18, weight: .regular)
        return v
    }()
    
    private lazy var middleLabel: UILabel = {
        let v = UILabel()
        v.text = "0"
        v.textColor = UIColor(0x808080)
        v.font = UIFont.systemFont(ofSize: 18, weight: .regular)
        return v
    }()
    
    private lazy var rightLabel3: UILabel = {
        let v = UILabel()
        v.text = "15"
        v.textColor = UIColor(0x808080)
        v.font = UIFont.systemFont(ofSize: 18, weight: .regular)
        return v
    }()
    
    private lazy var rightLabel2: UILabel = {
        let v = UILabel()
        v.text = "10"
        v.textColor = UIColor(0x808080)
        v.font = UIFont.systemFont(ofSize: 18, weight: .regular)
        return v
    }()
    
    private lazy var rightLabel1: UILabel = {
        let v = UILabel()
        v.text = "5"
        v.textColor = UIColor(0x808080)
        v.font = UIFont.systemFont(ofSize: 18, weight: .regular)
        return v
    }()
}

extension TiaoyinCanvasView {
    
    private func initializeSubviews() {
        layer.addSublayer(tickLayer1)
        layer.addSublayer(tickLayer2)
        layer.addSublayer(tickMiddleLayer)
        layer.addSublayer(leftLayer)
        layer.addSublayer(leftDarkLayer)
        layer.addSublayer(rightLayer)
        layer.addSublayer(rightDarkLayer)
//        layer.addSublayer(needleBgLayer)
        layer.addSublayer(topBorderLayer)        
        
        middleLabel.sizeToFit()
        addSubview(middleLabel)
        leftLabel3.sizeToFit()
        addSubview(leftLabel3)
        leftLabel2.sizeToFit()
        addSubview(leftLabel2)
        leftLabel1.sizeToFit()
        addSubview(leftLabel1)
        rightLabel3.sizeToFit()
        addSubview(rightLabel3)
        rightLabel2.sizeToFit()
        addSubview(rightLabel2)
        rightLabel1.sizeToFit()
        addSubview(rightLabel1)
        
        let needleHeight: CGFloat = radius + 15
        addSubview(needleView)
        needleView.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.bottom.equalTo(needleHeight * 0.5)
            make.height.equalTo(needleHeight)
            make.width.equalTo(18)
        }
    }
    
    private func drawArc() {
        
        let targetLeftAngle = targetAngle - 2.5
        let targetRightAngle = targetAngle + 2.5
        
        let path1 = UIBezierPath()
        path1.addArc(withCenter: radiusCenter, radius: radius, startAngle: startAngle * .pi / 180, endAngle: highlightStartAngle * .pi / 180, clockwise: true)
        leftLayer.path = path1.cgPath
        
        let path2 = UIBezierPath()
        path2.addArc(withCenter: radiusCenter, radius: radius, startAngle: highlightStartAngle * .pi / 180, endAngle: middleAngle * .pi / 180, clockwise: true)
        leftDarkLayer.path = path2.cgPath
        
        let path3 = UIBezierPath()
        path3.addArc(withCenter: radiusCenter, radius: radius, startAngle: middleAngle * .pi / 180, endAngle: highlightEndAngle * .pi / 180, clockwise: true)
        rightDarkLayer.path = path3.cgPath
        
        let path4 = UIBezierPath()
        path4.addArc(withCenter: radiusCenter, radius: radius, startAngle: highlightEndAngle * .pi / 180, endAngle: endAngle * .pi / 180, clockwise: true)
        rightLayer.path = path4.cgPath
        
        let topBorderPath = UIBezierPath()
        topBorderPath.addArc(withCenter: radiusCenter, radius: radius + 15, startAngle: startAngle * .pi / 180, endAngle: endAngle * .pi / 180, clockwise: true)
        topBorderLayer.path = topBorderPath.cgPath
        
        let needleBgPath = UIBezierPath()
        needleBgPath.addArc(withCenter: radiusCenter, radius: radius, startAngle: targetLeftAngle * .pi / 180, endAngle: targetRightAngle * .pi / 180, clockwise: true)
//        needleBgLayer.path = needleBgPath.cgPath
    }
    
    private func addTicks() {
        let center = radiusCenter
        let tickPath1 = UIBezierPath()
        let arrays: [CGFloat] = [-150 * .pi / 180, -130 * .pi / 180, -110 * .pi / 180, -90 * .pi / 180, -70 * .pi / 180, -50 * .pi / 180, -30 * .pi / 180]
        let middleTick = UIBezierPath()
        for i in 0..<arrays.count {
            let angle = arrays[i]
            var startOffset:CGFloat = 15
            if i == 0 || i == arrays.count - 1 {
                startOffset = -15
            }
            let startX = center.x + (radius + startOffset) * cos(angle)
            let startY = center.y + (radius + startOffset) * sin(angle)
            let endX = center.x + (radius + 20) * cos(angle)
            let endY = center.y + (radius + 20) * sin(angle)
            if i == 3 {
                middleTick.move(to: CGPoint(x: startX, y: startY))
                middleTick.addLine(to: CGPoint(x: endX, y: endY))
            } else {
                tickPath1.move(to: CGPoint(x: startX, y: startY))
                tickPath1.addLine(to: CGPoint(x: endX, y: endY))
            }
        }
        tickLayer1.path = tickPath1.cgPath
        tickMiddleLayer.path = middleTick.cgPath
            
        let tickPath2 = UIBezierPath()
        let arrays2: [CGFloat] = [-140 * .pi / 180, -120 * .pi / 180, -100 * .pi / 180, -80 * .pi / 180, -60 * .pi / 180, -40 * .pi / 180]
        for i in 0..<arrays2.count {
            let angle = arrays2[i]
            let startX = center.x + (radius + 15) * cos(angle)
            let startY = center.y + (radius + 15) * sin(angle)
            let endX = center.x + (radius + 18) * cos(angle)
            let endY = center.y + (radius + 18) * sin(angle)
            tickPath2.move(to: CGPoint(x: startX, y: startY))
            tickPath2.addLine(to: CGPoint(x: endX, y: endY))
        }
        
        tickLayer2.path = tickPath2.cgPath
    }
    
    private func adjustLabelsPosition() {
        let center = radiusCenter
        let tickPath1 = UIBezierPath()
        let arrays: [CGFloat] = [-150, -130, -110, -90, -70, -50, -30]
        let labels = [leftLabel1, leftLabel2, leftLabel3, middleLabel, rightLabel1, rightLabel2, rightLabel3]
        for i in 0..<arrays.count {
            let angle = arrays[i]
            let endX = center.x + (radius + 30) * cos(angle * .pi / 180)
            let endY = center.y + (radius + 30) * sin(angle * .pi / 180)
            labels[i].center = CGPoint(x: endX, y: endY)
            labels[i].transform = CGAffineTransform(rotationAngle: (angle + 90) * .pi / 180)
        }
    }
    
    private func createNeedlePath() -> CGPath {
        let path = UIBezierPath()
        let cornerRadius: CGFloat = 4
        path.move(to: CGPoint(x: bounds.midX, y: bounds.maxY))
        path.addArc(
            withCenter: CGPoint(x: bounds.midX, y: bounds.maxY - cornerRadius),
            radius: cornerRadius,
            startAngle: 0,
            endAngle: CGFloat.pi,
            clockwise: true
        )
        path.addLine(to: CGPoint(x: bounds.midX, y: bounds.minY))
        path.addLine(to: CGPoint(x: bounds.midX + cornerRadius, y: bounds.maxY - cornerRadius))
        path.close()
        return path.cgPath
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        guard !bounds.size.equalTo(.zero) else { return }
        drawArc()
        addTicks()
        adjustLabelsPosition()
    }
    
    func setValue(_ value: CGFloat) {
        targetAngle = value
        let newValue = (value + 90) * .pi / 180
        needleView.layer.anchorPoint = CGPoint(x: 0.5, y: 1.0)
        needleView.transform = CGAffineTransform(rotationAngle: newValue)
        needleView.isHidden = false
        setNeedsLayout()
    }
}

fileprivate class NeedleView: UIView {
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        initializeSubviews()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private let needleLayer = CAShapeLayer()
    
    private func initializeSubviews() {
        backgroundColor = .clear
        needleLayer.fillColor = UIColor(0xD3C390).cgColor
        layer.addSublayer(needleLayer)
        needleLayer.anchorPoint = CGPoint(x: 0.5, y: 1.0)
    }
    
    private func createNeedlePath() -> CGPath {
        let path = UIBezierPath()
        let cornerRadius: CGFloat = 4
        path.move(to: CGPoint(x: bounds.midX, y: bounds.maxY))
        path.addArc(
            withCenter: CGPoint(x: bounds.midX, y: bounds.maxY - cornerRadius),
            radius: cornerRadius,
            startAngle: 0,
            endAngle: CGFloat.pi,
            clockwise: true
        )
        path.addLine(to: CGPoint(x: bounds.midX, y: bounds.minY))
        path.addLine(to: CGPoint(x: bounds.midX + cornerRadius, y: bounds.maxY - cornerRadius))
        path.close()
        return path.cgPath
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        needleLayer.frame = bounds
        needleLayer.position = CGPoint(x: bounds.midX, y: bounds.maxY)
        needleLayer.path = createNeedlePath()
    }
}
